using System;
using System.Collections.Generic;
using System.Linq;

namespace Code_Generator
{
	public class DBColumn
	{
		public bool IsComputed { get; set; }
		public bool IsCreatedBy { get; set; }
		public bool IsCreatedDate { get; set; }
        public bool IsIdentity { get; set; }
		public bool IsNullable { get; set; }
		public bool IsPrimaryKey { get; set; }
		public bool IsRequired { get; set; }
		public bool IsUpdatedBy { get; set; }
		public bool IsUpdatedDate { get; set; }
        public int Length { get; set; }
		public string Precision { get; set; }
		public string Scale { get; set; }
		public string SqlDefault { get; set; }
		public string SqlName { get; set; }
		public string SqlType { get; set; }

		public bool IsAuditField
		{
			get { return IsCreatedBy || IsCreatedDate || IsUpdatedBy || IsUpdatedDate; }
		}

		public string ClrName
		{
			get { return SqlName.ToClrName(); }
		}


		public string SqlParameterName
		{
			get { return "@" + SqlName; }
		}

		public string ClrParameterName
		{
			get { return ClrName.Substring(0, 1).ToLower() + ClrName.Substring(1); }
		}

		public bool IsString
		{
			get { return ClrType == "string"; }
		}

		public string ClrTypeOverride { get; set; }

		public string ClrTypeNonNullable
		{
			get { return ClrTypeOverride ?? MapType(SqlType, false); }
		}

		public string ClrType
		{
			get { return ClrTypeOverride ?? MapType(SqlType, true); }
		}

		public bool HasSqlDefault
		{
			get { return SqlDefault != ""; }
		}

		private string MapType(string sqlType, bool allowNullable)
		{
			bool treatAsNullable = (IsNullable || !HasSqlDefault || IsAuditField || IsIdentity) ? allowNullable : false;
			switch (sqlType)
			{
				case "varchar":
				case "char":
				case "nvarchar":
				case "nchar":
				case "text":
				case "ntext":
					if (Length == 1)
						return "char?";
					else
						return "string";

				case "int":
					return ("int" + (treatAsNullable ? "?" : ""));

				case "decimal":
				case "numeric":
					return ("Decimal" + (treatAsNullable ? "?" : ""));

				case "smallint":
					return ("short" + (treatAsNullable ? "?" : ""));

				case "tinyint":
					return ("byte" + (treatAsNullable ? "?" : ""));

				case "bit":
					return ("bool" + (treatAsNullable ? "?" : ""));

				case "datetime":
				case "date":
					return ("DateTime" + (treatAsNullable ? "?" : ""));

				case "datetimeoffset":
					return ("DateTimeOffset" + (treatAsNullable ? "?" : ""));

				case "time":
					return ("TimeSpan" + (treatAsNullable ? "?" : ""));

				case "uniqueidentifier":
					return ("Guid" + (treatAsNullable ? "?" : ""));

				default:
					throw new Exception("Unknown sql type " + sqlType);
			}
		}

		public bool IsTokenColumn { get; set; }

		public string FullSqlType
		{
			get
			{
				switch (SqlType)
				{
					case "char":
						return String.Format("{0}({1})", SqlType.ToUpper(), Length);
					case "nchar":
						return String.Format("{0}({1})", SqlType.ToUpper(), (Length / 2));

					case "varchar":
						return String.Format("{0}({1})", SqlType.ToUpper(), (Length == -1 ? "MAX" : Length.ToString()));

					case "nvarchar":
						return String.Format("{0}({1})", SqlType.ToUpper(), (Length == -1 ? "MAX" : (Length / 2).ToString()));
						
					case "decimal":
					case "numeric":
						return String.Format("{0}({1},{2})", SqlType.ToUpper(), Precision, Scale);

					default:
						return SqlType.ToUpper();
				}
			}
		}
	}
}
